Air Monitoring Data

Data dictionary for the air monitoring data published by Martinez Refining Company: every field in every data set, what it holds and what type it is.

Looking for the API? How to call each endpoint, its parameters, rate limits and worked request and response examples are in the API documentation.

Four data sets are published, for four different purposes:

Data setWhat it isManual downloadAPI
Fenceline Monitoring Data Five-minute average pollutant concentrations, one record per instrument, parameter and averaging period, with detection limits, quality codes and instrument signal. CSV, XML CSV, JSON
GLM Data Five-minute average concentrations from the four ground level monitors operated under Air District Rules 9-1 and 9-2. Hydrogen sulfide at all four, sulfur dioxide at Ace Hardware. CSV, XML CSV, JSON
Monitoring Locations Where each analyzer, reflector, light source, met station and ground level monitor sits, and what it reports. Fixed positions, so there is no date range. CSV, GeoJSON, shapefile CSV, JSON, GeoJSON
Current Readings The single latest reading for every monitoring location and property, as shown on the public dashboard. Includes weather properties. None JSON

Fenceline Monitoring Data

Real-time data comes only from the API. The manual download stops one averaging period short of the present moment. To read the most recent five-minute period, use the API.

Data dictionary

Every field below carries the same name in CSV, XML and JSON, and the fields appear in the same order in all three.

Ozone appears on the public dashboard and in Current Readings, and not in this data set. The four beam paths measure it as a quality cross-check against a nearby reference station, not as a fenceline pollutant.

QC_code and error_codes both describe data quality, and they are not interchangeable. QC_code gives the specific flag number defined in the Quality Assurance Project Plan. error_codes gives the broad category that flag falls into, and many flags fall into none of the categories, so it reads empty on plenty of flagged readings. Read QC_code when the precise flag matters.

FieldTypeDescription
facility_nametext The facility where the equipment sits. Always Martinez Refining Company.
instrument_idtext Identifier for the instrument that produced the measurement. One identifier per physical analyzer, shared by every parameter that analyzer measures.
instrumenttext Short descriptive name for the instrument, pairing its monitoring location with its analyzer type: UV-DOAS, TDL, FTIR or OGD.
parametertext Name of the pollutant measured and reported, for example Benzene or Total Alkanes.
datetext, yyyy-mm-dd Date of measurement, in Pacific Standard Time with no adjustment for daylight saving.
timetext, hh:mm Start of the five-minute period the measurements cover, in 24-hour notation, in Pacific Standard Time with no adjustment for daylight saving.
mean_concentrationnumber Arithmetic mean pollutant concentration over the averaging period. Where a reading falls below the limit of quantification the instrument achieved for it, this field carries half that limit; real_time_loq carries the limit itself.
units_of_measuretext Units for mean_concentration, for example ppb.
averaging_periodinteger, minutes Length of the period the mean concentration covers. Always 5.
observation_countinteger How many individual instrument readings the reported mean covers. It differs by analyzer type, because each samples at its own rate across the five-minute period. A UV-DOAS row reads 1: that analyzer averages internally and delivers one value per period. An FTIR row gives the number of interferogram scans co-added into its spectrum. A row reads empty where its instrument records no count of its own.
validity_indicatorY or N Whether the reported mean concentration represents a valid air measurement. N covers a light signal too weak or too strong to trust, humidity above the instrument's operating range, an instrument fault, and QA or test mode instead of ambient sampling. Every quality flag the reading carried decides this, not only the flag published in QC_code.
error_codestext The broad data quality category assigned to the measurement: Missing, Invalid, Low Signal, Weather or QA. Empty for a reading with no quality issue, and empty as well where the reading's flag falls into none of those categories, which is common. See QC_code for the underlying flag.
max_valuenumber Carries the same value as mean_concentration. Each record describes a single five-minute average, so it holds no separate maximum of its own.
required_loqnumber The limit of quantification the Quality Assurance Project Plan requires for this instrument and pollutant. A fixed target, unlike real_time_loq.
real_time_loqnumber The limit of quantification the instrument achieved for this reading, in the same units as mean_concentration. It is calculated per reading, so it moves over time. This quantity also goes by real-time minimum detection limit, or MDL.
signalnumber Mean measured light signal over the averaging period, or the mean of the alternative parameter the instrument uses to monitor its light signal.
signal_unitstext Units for signal. These differ by analyzer type, because each type monitors its signal differently: light count for UV-DOAS, % full scale for FTIR, %transmission for TDL, and mA for OGD, whose signal is the analyzer's 4 to 20 mA current loop.
QC_codetext The data quality flag assigned to the measurement, given as the flag number defined in the Quality Assurance Project Plan. Empty for a reading that carried no flag, and Missing for an averaging period the instrument never reported.

A single reading can trip more than one quality check. This column gives the governing flag for that reading, and where any flag present invalidates the reading, the governing flag is one of those. validity_indicator weighs every flag on the reading.
final_dataY or N Whether the record has cleared final quality assurance review. N marks a preliminary record. Every record published to date reads N.
change_logtext Description of any change made to the record, with the date of the change. Empty for an unchanged record, which so far is all of them.

Missing measurements

A record with no pollutant concentration still gets published, whether the instrument recorded the period without producing a concentration or never reported for that period at all. It keeps facility_name, instrument_id, instrument, parameter, date, time, QC_code and error_codes. Every remaining field, the text ones included, carries -9999. A negative value in any of those fields therefore means "not available" and never a real measurement.

A period that has not finished yet does not count as missing data. The export drops the most recently started five-minute period until it has fully elapsed. Instruments can also write their data a few minutes late, so a very recent period may read as missing until its record lands.

GLM Data

A separate data set from the Fenceline Monitoring Data. The ground level monitors are operated under Air District Rules 9-1 and 9-2, and their records carry four fewer fields: no real_time_loq, signal, signal_units or QC_code. Every other field means exactly what it means in the Fenceline Monitoring Data above.

Data dictionary

Sixteen fields, in the same order as their Fenceline Monitoring Data counterparts, so the two files line up column for column where they overlap.

FieldTypeDescription
facility_nametextAlways "Martinez Refining Company".
instrument_idtextIdentifier for the monitor: glm_ace, glm_mtview, glm_shellave or glm_etp.
instrumenttextThe monitor's name, for example "Ace GLM".
parametertext"Hydrogen Sulfide" or "Sulfur Dioxide".
datedateDate of measurement, Pacific Standard Time, yyyy-mm-dd.
timetimeStart of the five-minute period, Pacific Standard Time, hh:mm.
mean_concentrationnumberMean concentration over the period, in ppb.
units_of_measuretextAlways "ppb".
averaging_periodnumberAlways 5, in minutes.
observation_countnumberValues behind the mean. Blank while the monitors do not report a count.
validity_indicatortext"Y" or "N". Every reading is currently "Y": the monitors publish no quality flags yet.
error_codestextReason a reading is invalid or missing. "Missing" on a period the monitor did not report; otherwise blank until the monitors supply error codes.
max_valuenumberHighest value in the period. Equal to mean_concentration while the monitors report one value per period.
required_loqnumberRequired limit of quantification. Blank: no required LoQ is set for the ground level monitors.
final_datatext"Y" once a record is final quality-assured data. Currently always "N".
change_logtextDescription of any change made to the record. Currently always blank.

Missing measurements

A five-minute period the monitor did not report still produces a record. It keeps facility_name, instrument_id, instrument, parameter, date and time, sets error_codes to "Missing", and sets every other field to -9999.

Not yet reporting

The data feed for these monitors is still being built. Until it is in place every period returns a "Missing" record as described above, and the dashboard shows a dash rather than a reading.

Monitoring Locations

Where each monitoring instrument sits, and what it reports. There is no date range; these are fixed installation positions. Each published point gets one record: a point instrument, the met station and each ground level monitor have one apiece, and an open path has two. Both ends of a path share an instrument_id and are told apart by the instrument name.

The two open path instrument types are built differently, so the far end of a path is not the same thing in both cases. A TDL sends its beam to a corner cube reflector and reads the return at the analyzer, so its two points are Open Path Analyzer and Reflector. A UV-DOAS puts a lamp at one end and the analyzer at the other, with no reflector on the path at all, so its two points are Open Path Analyzer and Light Source. The analyzer end carries that name in both cases.

Data dictionary

FieldTypeDescription
facility_nameText The facility where the equipment sits.
instrument_idText Identifier for the instrument. Both ends of an open path share one, because they are one instrument.
instrumentText Descriptive name for the instrument, including which end of an open path the point is, as described above.
parametersText The pollutants that instrument reports, comma separated. Empty where an instrument's parameters are not yet confirmed.
latitudeNumber Decimal degrees, north positive, to six places.
longitudeNumber Decimal degrees, east positive, to six places.

In GeoJSON the same six fields appear as each feature's properties, and the geometry is a Point whose coordinates read [longitude, latitude]. The GeoJSON specification fixes that order, which reverses the column order above.

A shapefile's attribute table is dBASE, which limits field names to ten characters, so two of them get shortened in that format alone: facility_name becomes FACILITY and instrument_id becomes INSTR_ID. The other four keep their names in upper case. CSV, JSON and GeoJSON all use the full names above.

Not yet published

Current Readings

This endpoint takes no parameters. Every request returns the same thing: the latest reading for every monitored location and property as of the moment of the request, covering every pollutant at every monitoring location plus every weather property at the met station. Ozone appears here; the Fenceline Monitoring Data leaves it out. There is no way to ask this endpoint for a specific location, property or date range. For those, use the Fenceline Monitoring Data API, or the Download Data page.

GET /api-data.php
{
  "generatedAt": "2026-07-28T20:45:00+00:00",
  "records": [
    {
      "site": "path1",
      "siteName": "Path 1",
      "property": "ben",
      "propertyName": "Benzene",
      "unit": "ppb",
      "timestamp": "2026-07-28T20:45:00+00:00",
      "value": 0.246609,
      "loq": 0.493218,
      "description": "No Detection",
      "online": true
    },
    {
      "site": "met",
      "siteName": "Met",
      "property": "wind_speed",
      "propertyName": "Wind Speed",
      "unit": "mph",
      "timestamp": "2026-07-28T20:45:00+00:00",
      "value": 5.9,
      "loq": null,
      "description": null,
      "online": true
    }
  ]
}

Data dictionary

FieldTypeDescription
sitetextMonitoring location key, for example path1 or met.
siteNametextHuman-readable location name, for example "Path 1".
propertytextGas or weather property key, for example ben or wind_speed.
propertyNametextHuman-readable property name, for example "Benzene".
unittext or nullUnit of measurement, for example ppb or mph. null if unitless.
timestamptext, ISO 8601 UTCTime of the latest reading. This differs from the Fenceline data set, which uses Pacific Standard Time in separate date and time fields.
valuenumberThe measured value. A non-detect arrives already substituted at half the gas's Limit of Quantification, which is standard practice for a value below a reporting limit; description says when that substitution applied.
loqnumber or nullLimit of Quantification for this gas and location, per reading where the instrument reports one. Always null for weather properties.
descriptiontext or nullData status or quality label, and null for a normal valid reading. The Learning Center lists what each label means.
onlinetrue or falseWhether the source instrument reported data recently enough to count as online.

This endpoint takes no input, so there is little to get wrong: exceeding the rate limit returns HTTP 429, and any other non-200 response points to a server-side problem and not to the request.

The website's Learning Center defines the terms and acronyms used here, explains each data status label, and lists the current Limit of Quantification for every gas and monitoring location.

The Documents page holds the Fence Line Air Monitoring Plan, the Quality Assurance Project Plan and the quarterly monitoring reports.

The Download Data page provides the Fenceline Monitoring Data as CSV or XML over a chosen date range, stopping five minutes short of the present as above, and the Monitoring Locations as CSV, GeoJSON or shapefile.